package handler

import (
	"math"
	"reflect"
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// PaginationParams 分页参数
type PaginationParams struct {
	Page     int `json:"page"`
	PageSize int `json:"page_size"`
}

// PaginationInfo 分页信息
type PaginationInfo struct {
	Page       int   `json:"page"`
	PageSize   int   `json:"page_size"`
	Total      int64 `json:"total"`
	TotalPages int   `json:"total_pages"`
	HasNext    bool  `json:"has_next"`
	HasPrev    bool  `json:"has_prev"`
}

// PaginatedResponse 分页响应
type PaginatedResponse struct {
	Data       interface{}    `json:"data"`
	Pagination PaginationInfo `json:"pagination"`
	Count      int            `json:"count"`
}

// GetPaginationParams 从请求中获取分页参数
func GetPaginationParams(c *gin.Context) PaginationParams {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

	// 参数验证和修正
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 10
	}

	return PaginationParams{
		Page:     page,
		PageSize: pageSize,
	}
}

// PaginateQuery 执行分页查询
func PaginateQuery(db *gorm.DB, params PaginationParams, result interface{}) (*PaginatedResponse, error) {
	var total int64

	// 获取总数
	if err := db.Count(&total).Error; err != nil {
		return nil, err
	}

	// 计算偏移量
	offset := (params.Page - 1) * params.PageSize

	// 执行分页查询
	if err := db.Offset(offset).Limit(params.PageSize).Find(result).Error; err != nil {
		return nil, err
	}

	// 计算分页信息
	pagination := calculatePagination(params, total)

	// 获取结果数量
	resultCount := getSliceLength(result)

	return &PaginatedResponse{
		Data:       result,
		Pagination: pagination,
		Count:      resultCount,
	}, nil
}

// PaginateQueryWithOrder 执行带排序的分页查询
func PaginateQueryWithOrder(db *gorm.DB, params PaginationParams, order string, result interface{}) (*PaginatedResponse, error) {
	return PaginateQuery(db.Order(order), params, result)
}

// PaginateQueryWithCondition 执行带条件的分页查询
func PaginateQueryWithCondition(db *gorm.DB, params PaginationParams, condition string, args ...interface{}) func(result interface{}) (*PaginatedResponse, error) {
	return func(result interface{}) (*PaginatedResponse, error) {
		return PaginateQuery(db.Where(condition, args...), params, result)
	}
}

// PaginateSlice 对切片进行分页
func PaginateSlice(slice interface{}, params PaginationParams) *PaginatedResponse {
	sliceLen := getSliceLength(slice)

	// 计算分页信息
	pagination := calculatePagination(params, int64(sliceLen))

	// 计算分页范围
	offset := (params.Page - 1) * params.PageSize
	end := offset + params.PageSize
	if end > sliceLen {
		end = sliceLen
	}

	var paginatedData interface{}
	if offset < sliceLen {
		paginatedData = sliceToInterface(slice, offset, end)
	}

	return &PaginatedResponse{
		Data:       paginatedData,
		Pagination: pagination,
		Count:      end - offset,
	}
}

// calculatePagination 计算分页信息
func calculatePagination(params PaginationParams, total int64) PaginationInfo {
	totalPages := int(math.Ceil(float64(total) / float64(params.PageSize)))
	hasNext := params.Page < totalPages
	hasPrev := params.Page > 1

	return PaginationInfo{
		Page:       params.Page,
		PageSize:   params.PageSize,
		Total:      total,
		TotalPages: totalPages,
		HasNext:    hasNext,
		HasPrev:    hasPrev,
	}
}

// getSliceLength 获取切片长度
func getSliceLength(slice interface{}) int {
	switch v := slice.(type) {
	case []interface{}:
		return len(v)
	case []map[string]interface{}:
		return len(v)
	case []string:
		return len(v)
	case []int:
		return len(v)
	case []float64:
		return len(v)
	default:
		// 使用反射获取长度
		return getSliceLengthByReflection(slice)
	}
}

// sliceToInterface 将切片转换为接口类型
func sliceToInterface(slice interface{}, start, end int) interface{} {
	switch v := slice.(type) {
	case []interface{}:
		if start < len(v) {
			if end > len(v) {
				end = len(v)
			}
			return v[start:end]
		}
		return []interface{}{}
	case []map[string]interface{}:
		if start < len(v) {
			if end > len(v) {
				end = len(v)
			}
			return v[start:end]
		}
		return []map[string]interface{}{}
	case []string:
		if start < len(v) {
			if end > len(v) {
				end = len(v)
			}
			return v[start:end]
		}
		return []string{}
	case []int:
		if start < len(v) {
			if end > len(v) {
				end = len(v)
			}
			return v[start:end]
		}
		return []int{}
	case []float64:
		if start < len(v) {
			if end > len(v) {
				end = len(v)
			}
			return v[start:end]
		}
		return []float64{}
	default:
		return getSliceByReflection(slice, start, end)
	}
}

// getSliceLengthByReflection 使用反射获取切片长度
func getSliceLengthByReflection(slice interface{}) int {
	v := reflect.ValueOf(slice)
	if v.Kind() == reflect.Slice {
		return v.Len()
	}
	return 0
}

// getSliceByReflection 使用反射获取切片片段
func getSliceByReflection(slice interface{}, start, end int) interface{} {
	v := reflect.ValueOf(slice)
	if v.Kind() == reflect.Slice {
		if start < v.Len() {
			if end > v.Len() {
				end = v.Len()
			}
			return v.Slice(start, end).Interface()
		}
	}
	return []interface{}{}
}
